Appearance
简介
网页端运行的ffmpeg,纯靠网页中的依赖,不需要依赖环节变量ffmpeg。 具体与命令行工具具体有何区别,没空研究,性能估计只有本体的三分之一。
前言
记录当前文档的主要原因,是此依赖包有过一次大版本更新,大量的最新api没有被llm大语言模型收录,查阅资料的时候极其容易跑偏。 故此,当前文档内每一个功能都完成了可行性验证。
信息
version:"@ffmpeg/ffmpeg": "^0.12.15", "@ffmpeg/util": "^0.12.2" data:2025/08/18
创建
依赖
npm install @ffmpeg/ffmpeg @ffmpeg/utilvite.config.ts
ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
server: {
headers: {
'Cross-Origin-Embedder-Policy': 'require-corp',
'Cross-Origin-Opener-Policy': 'same-origin',
},
},
worker: {
format: 'es',
},
plugins: [vue()],
optimizeDeps: {
exclude: ["@ffmpeg/ffmpeg"] // *重点 - 防止预构建的过程中丢失路径
}
})加载
ts
import { FFmpeg } from '@ffmpeg/ffmpeg'
import { fetchFile, toBlobURL } from '@ffmpeg/util'
const ffmpeg = new FFmpeg(); // 新的版本需要在此导入实例
onMounted(async () => {
const baseURL = '/ffmpeg' // 考虑网络稳定性,建议下载到public
// const baseURL = 'https://unpkg.com/@ffmpeg/core@0.12.10/dist/esm'
await ffmpeg.load({
coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'),
wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, 'application/wasm'),
workerURL: await toBlobURL(`${baseURL}/ffmpeg-core.worker.js`, 'text/javascript'),
});
console.log('ffmpeg加载完成');
})常用方法
独立功能实现
截取时间
本part主要关注,基于原本封装格式不变,裁切视频内容。
ts
const transcode = async (
{ type, file, input, output }:
{ type: string, file: File, input: number, output: number }
) => {
const buffer = new Uint8Array(await fetchFile(URL.createObjectURL(file)));
await ffmpeg.writeFile('input.' + type, buffer);
await ffmpeg.exec([
'-i', `input.${type}`, // 输入
'-ss', input + '', // 开始时间
'-t', output - input + '', // 持续时间
'-c', 'copy', // 直接复制流,*速度极快*
`output.${type}`
]);
const data = await ffmpeg.readFile('output.' + type);
download(data);
}编解码
本part主要关注,将不同格式的文件转换成mp4文件。
分辨率
本part主要关注,基于一个固定分辨率的画布上,加入视频素材。
变形
本part主要关注,位移、缩放、旋转
组合拳
组合实现
叠轨
相关方法
download
js
const download = (data,type) => {
const a = document.createElement('a');
a.href = URL.createObjectURL(new Blob([data.buffer], { type: 'type/type' }))
a.download = 'output.type';
a.click();
a.remove();
}